package com.tomtop.core.web.interceptor;

import java.io.Serializable;
import java.util.LinkedList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.google.common.collect.Lists;
import com.tomtop._const.Const;
import com.tomtop.core.Context;

/**
 * 校验重复的相同的http请求
 * 
 * @author Administrator
 *
 */
@Component
@ConfigurationProperties(prefix="spring.crri")
public class CheckRepeatRequestInterceptor extends HandlerInterceptorAdapter {
	
	private final static Logger logger = LoggerFactory.getLogger(CheckRepeatRequestInterceptor.class);

	private String redirectUrl;
	private String[] filterUrl;
	public void setFilterUrl(String[] filterUrl) {
		this.filterUrl = filterUrl;
	}
	public void setRedirectUrl(String redirectUrl) {
		this.redirectUrl = redirectUrl;
	}
	
	@Override
	public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {
		String url = request.getRequestURI();
		if(!filterLogger(url))
			return true;
		HttpSession session = request.getSession();
		 if(judge(session, url)){
			 if(logger.isDebugEnabled())
				 logger.debug("判断出当前请求没有重复超次请求");
			 return true;
		 }
		 if(logger.isInfoEnabled())
			 logger.info("判断出当前请求是重复超次请求");
		 Context.sendRedirect(redirectUrl);
		return false;
	}
	
	/**
	 * 判断是否是一个时间段内连续提交超过达到指定次数
	 * @param session
	 * @param url
	 * @return 返回false，表示超过了，返回true表示没有超过
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean judge(HttpSession session,String url){
		LinkedList<RequestTime> list=(LinkedList) session.getAttribute(Const.CHECKREPEAT_SESSION_NAME);
		long localtime=System.currentTimeMillis();
		if((list==null&&(list=Lists.newLinkedList())!=null)||list.size()<Const.CHECK_REPEAT_REQUEST_COUNT){//第一次访问,或者未达到访问次数的限制
			list.add(new RequestTime(url, localtime));
			session.setAttribute(Const.CHECKREPEAT_SESSION_NAME, list);
			return true;
		}
		list.removeLast();//达到访问次数限制，就从队列最后删除一个
		IsOK isok=new IsOK();
		list.forEach(rt->{
			long time=localtime-rt.requestTime-Const.CHECK_REPEAT_REQUEST_TIME*1000;
			if(time>0||url==null||!url.equals(rt.url)){//在访问限制数内，任意一个不符合限制要求（时间范围，url是否相同），就不做限制
				isok.isok =true;
			}
		});
 		list.addFirst(new RequestTime(url,localtime));//添加到队列的开头
		session.setAttribute(Const.CHECKREPEAT_SESSION_NAME, list);
		return isok.isok;
	}
	private class IsOK{ private boolean isok=false; }
	public static class RequestTime implements Serializable{
		/**
		 * 
		 */
		private static final long serialVersionUID = 4127267503418277160L;
		private String url;
		private Long requestTime;
		public RequestTime(String url,Long requestTime) {
			this.url=url;
			this.requestTime=requestTime;
		}
	}
	
	private boolean filterLogger(final String url) {
		if(url==null)
			return false;
		for (String furl : filterUrl) {
			if(url.matches("^"+furl))
				return true;
		}
		return false;
	}

	@Override
	public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final ModelAndView modelAndView) throws Exception { super.postHandle(request, response, handler, modelAndView); }

	@Override
	public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception ex) throws Exception { }
}